﻿#pragma once


//包含了Windows.h,大量宏 恶心心
#include "RtAudio.h"
#include "RtAudioWrapper.h"
#include <string.h>

RtAudioWarpper::RtAudioWarpper()
{
    Stream = new RtAudio();
}

RtAudioWarpper::~RtAudioWarpper()
{
    if (Stream)
    {
        if(Stream->isStreamRunning())
        {
            Stream->stopStream();
        }
        if(Stream->isStreamOpen())
        {
            Stream->closeStream();
        }
        delete Stream;
        Stream = nullptr;
    }
}

void RtAudioWarpper::StartStream()
{
    Stream->startStream();
}

void RtAudioWarpper::StopStream()
{
    Stream->stopStream();
}

bool RtAudioWarpper::IsStreamRunning()
{
    return Stream->isStreamRunning();
}

/// @brief 
/// @param outputBuffer 
/// @param  
/// @param nBufferFrames 
/// @param  
/// @param  
/// @param data 
/// @return  0表示正常，1表示播放结束
int CopyData( void *outputBuffer, void * /*inputBuffer*/, unsigned int nBufferFrames,
            double /*streamTime*/, RtAudioStreamStatus /*status*/, void *data )
{
    RtAudioWarpper * MyData = (RtAudioWarpper*)data;
    auto CopyedFrameNum=MyData->DataGetter.Execute(outputBuffer, nBufferFrames);

    if(CopyedFrameNum==nBufferFrames)
    {
        return 0;
    }
    else
    {
        //数据不够,剩余部分填充0
        memset((uint8_t*)outputBuffer+ CopyedFrameNum*MyData->GetFrameDataSize() 
             ,0
             , (nBufferFrames - CopyedFrameNum) *MyData-> GetFrameDataSize());
        return 1;
    }

}


void RtAudioWarpper::OpenStream(
    int64_t InSampleRate
    , int64_t InNumChannels
    , int64_t InBitsPerSample)
{

    RtAudio::StreamParameters parameters;
    parameters.deviceId = Stream->getDefaultOutputDevice();
    parameters.nChannels = InNumChannels;
    parameters.firstChannel = 0;

    unsigned int bufferFrames = 512;
    unsigned int sampleRate = InSampleRate;
    unsigned int channels = InNumChannels;
    unsigned int bitsPerSample = InBitsPerSample;
    FrameDataSize=channels*bitsPerSample/8;

    RtAudio::StreamOptions options;
    options.flags = RTAUDIO_SCHEDULE_REALTIME;
    options.numberOfBuffers = 1;
    options.priority = 1;



    RtAudioFormat format = RTAUDIO_SINT16;
    switch(InBitsPerSample)
    {
        case 8:
            format = RTAUDIO_SINT8;
            break;
        case 16:
            format = RTAUDIO_SINT16;
            break;
        case 24:
            format = RTAUDIO_SINT24;
            break;
        case 32:
            format = RTAUDIO_SINT32;
            break;
        default:
            assert(false);
            break;
    }

    Stream->openStream(
        &parameters
        , nullptr
        , format
        , sampleRate
        , &bufferFrames
        , &CopyData
        , this
        , &options);
    
}

void RtAudioWarpper::CloseStream()
{
    Stream->closeStream();
}

bool RtAudioWarpper::IsStreamOpened()
{
    return Stream->isStreamOpen();
}
